/*
Copyright (C) 2006  Mark Garner

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
using System.Data;
using System.Data.SqlClient;

namespace NDataUnit
{
    class TestSuite
    {
        string _testScriptPath = string.Empty;
        string _outputLogFilePath = string.Empty;
        string _targetServerName = string.Empty;
        string _targetDatabaseName = string.Empty;

        public TestSuite()
        {
        }

        public TestSuite(string TestScriptPath, string TargetServerName, string TargetDatabaseName)
        {
            _testScriptPath = TestScriptPath;
            _targetServerName = TargetServerName;
            _targetDatabaseName = TargetDatabaseName;
        }

        public TestSuite(string TestScriptPath, string OutputLogFilePath, string TargetServerName, string TargetDatabaseName)
        {
            _testScriptPath = TestScriptPath;
            _targetServerName = TargetServerName;
            _targetDatabaseName = TargetDatabaseName;
            _outputLogFilePath = OutputLogFilePath;
        }

        public string TestScriptPath
        {
            get { return _testScriptPath; }
            set { _testScriptPath = value; }
        }

        public string TargetServerName
        {
            get { return _targetServerName; }
            set { _targetServerName = value; }
        }

        public string TargetDatabaseName
        {
            get { return _targetDatabaseName; }
            set { _targetDatabaseName = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns>Number of failed tests</returns>
        public int Run()
        {
            bool doLogOutput = false;
            LogWriter logWriter = new LogWriter() ;
            if (_outputLogFilePath != string.Empty)
            {
                doLogOutput = true;
                logWriter.OutputLogFilePath = _outputLogFilePath;
            }

            if (this.TestScriptPath == string.Empty)
            {
                throw new Exception("Test script path not provided");
            }

            if (!File.Exists(this.TestScriptPath))
            {
                throw new Exception("Test script file not found");
            }

            SqlConnection connection = new SqlConnection();
            connection.ConnectionString = "Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=" + this.TargetDatabaseName + ";Data Source=" + this.TargetServerName;
            connection.Open();

            XmlDocument testsDoc = new XmlDocument();
            testsDoc.Load(this.TestScriptPath);

            XmlNodeList tests = testsDoc.SelectNodes("/TestSuite/Test");
            int failureCount = 0;
            foreach (XmlNode test in tests)
            {
                SqlCommand command = connection.CreateCommand();
                command.CommandText = test.SelectSingleNode("QueryText").InnerText;

                SqlDataReader reader = command.ExecuteReader();
                if (reader.Read())
                {
                    XmlNodeList expectedValues = test.SelectNodes("ExpectedValues/Value");
                    foreach (XmlNode value in expectedValues)
                    {
                        string columnName = value.Attributes["ColumnName"].Value;
                        string returnedValue = Convert.ToString(reader[columnName]);
                        string expectedValue = value.InnerText;
                        string dataType = value.Attributes["DataType"].Value;

                        Decimal returnedValueD = 0;
                        Decimal expectedValueD = 0;

                        bool isEqual = false;

                        if (dataType.ToUpper() == "NUMBER")
                        {
                            returnedValueD = Convert.ToDecimal(returnedValue);
                            expectedValueD = Convert.ToDecimal(expectedValue);

                            if (returnedValueD == expectedValueD)
                                isEqual = true;
                        }

                        if (dataType.ToUpper() == "STRING")
                        {
                            if (returnedValue == expectedValue)
                                isEqual = true;
                        }

                        if ( !isEqual )
                        {
                            failureCount++;

                            if (doLogOutput)
                            {
                                string line = String.Empty;
                                line += "\"" + test.SelectSingleNode("Name").InnerText + "\"";
                                line += " on value \"" + columnName + "\" FAILED: ";
                                if (dataType.ToUpper() == "NUMBER")
                                {
                                    line += Convert.ToString(returnedValueD) + " was not equal to the expected value of " + Convert.ToString(expectedValueD);
                                }
                                if (dataType.ToUpper() == "STRING")
                                {
                                    line += "\"" + returnedValue + "\" was not equal to the expected value of \"" + expectedValue + "\"";
                                }
                                logWriter.WriteToLog(line);
                            }
                        }
                        else
                        {
                            if (doLogOutput)
                            {
                                string line = String.Empty;
                                line += "\"" + test.SelectSingleNode("Name").InnerText + "\"";
                                line += " on value \"" + columnName + "\" was successful";
                                logWriter.WriteToLog(line);
                            }
                        }
                    }
                }
                else
                {
                    string testName = test.SelectSingleNode("Name").InnerText;
                    throw new Exception("Test named \"" +testName + "\" returned no rows");
                }
                reader.Close();
            }

            return failureCount;
        }
    }
}
